/*
 * Power.cpp
 *
 *  Created on: Dec 28, 2008
 *      Author: sez
 */

#include "Power.h"

#include <Xml/Xml.h>
#include <Xml/XmlPath.h>

const char *Power::POWER_TYPE_NAMES[] =
{ "Attack", "Utility" };

const char *Power::POWER_SOURCE_NAMES[] =
{ "Divine", "Martial", "Arcane" };

const char *Power::POWER_AVAILABILITY_NAMES[] =
{ "At Will", "Encounter", "Daily", "Recharge" };

const char *Power::ACTION_COST_NAMES[] =
{ "No Action", "Free Action", "Immediate Interrupt", "Immediate Reaction",
		"Minor Action", "Standard Action", "Move Action" };

const char *Power::RANGE_TYPE_NAMES[] =
{ "Melee Range", "Melee Weapon Range", "Melee Touch", "Melee One",
		"Close Range", "Close Burst", "Close Blast", "Ranged", "Ranged Sight",
		"Ranged Weapon", "Area Blast", "Area Burst" };

Power::Power(const XmlPath &path)
    : TitledData(path.objectName())
    , base(path.type())
    , baseTypeName(path.typeName())
{
    if (base == XmlPath::CLASS_BASE)
    {
        QString className = path.typeName();
        int i;
        for (i = 0; i < DndData::NUM_CLASSES; ++i)
            if (className == DndData::CLASS_NAMES[i])
                break;
        if (i != DndData::NUM_CLASSES)
            associatedClass = static_cast<DndData::ClassName>(i);
        else
            extAssociatedClass = className;
    }
}

Power::Power(const QString &title)
    : TitledData(title)
{
}

Power::Power(const Power &rhs)
	: TitledData(rhs.title())
{
    this->level = rhs.level;
    this->text = rhs.text;
    this->type = rhs.type;
    this->availability = rhs.availability;
    this->associatedClass = rhs.associatedClass;
    this->keywords = rhs.keywords;
    this->actionCost = rhs.actionCost;
    this->range = rhs.range;
    this->trigger = rhs.trigger;
    this->prerequisite = rhs.prerequisite;
    this->requirement = rhs.requirement;
    this->target = rhs.target;
    this->hit = rhs.hit;
    this->miss = rhs.miss;
    this->detail = rhs.detail;
}

Power::~Power()
{
}

void Power::saveToXml() const
{
    XmlPath path(base, XmlPath::safeDataPathName(title()));
    path.setSubType(XmlPath::POWER_TYPE);
    Xml xml(path);
    xml.appendTag("Title", title());
    appendTag(xml, "Level", level);
    xml.appendTag("Text", text);
    appendTag(xml, "Type", type);
    appendTag(xml, "Availability", availability);
    appendTag(xml, "AssociatedClass", associatedClass);
    appendTag(xml, "ExtAssociatedClass", extAssociatedClass);
    xml.appendArray("Keywords", keywords);
    appendTag(xml, "ActionCost", actionCost);
    appendTag(xml, "Range", range);
    xml.appendTag("Trigger", trigger);
    xml.appendTag("Prerequisite", prerequisite);
    xml.appendTag("Requirement", requirement);
    xml.appendTag("Target", target);
    xml.appendTag("Hit", hit);
    xml.appendTag("Miss", miss);
    xml.appendTag("Detail", detail);
    xml.serializeXml();
}

void Power::loadFromXml()
{
    XmlPath path(base, XmlPath::safeDataPathName(title()));
    path.setSubType(XmlPath::POWER_TYPE);
    Xml xml(path);
    xml.deserializeXml();
    setTitle(xml.value("Title"));
    level = value<int>(xml, "Level");
    text = xml.value("Text");
    type = value<Power::PowerType>(xml, "Type");
    availability = value<Power::PowerAvailability>(xml, "Availability");
    associatedClass = value<DndData::ClassName>(xml, "AssociatedClass");
    extAssociatedClass = xml.value("ExtAssociatedClass");
    keywords = xml.valueArray("Keywords");
    actionCost = value<Power::ActionCost>(xml, "ActionCost");
    range = value<Power::RangeType>(xml, "Range");
    trigger = xml.value("Trigger");
    prerequisite = xml.value("Prerequisite");
    requirement = xml.value("Requirement");
    target = xml.value("Target");
    hit = xml.value("Hit");
    miss = xml.value("Miss");
    detail = xml.value("Detail");
}

QString Power::description() const
{
	return QString("%1 %2 %3 power").arg(POWER_AVAILABILITY_NAMES[availability]).arg(
			RANGE_TYPE_NAMES[range]).arg(POWER_TYPE_NAMES[type]);
}

Power &Power::operator=(const Power &rhs)
{
	this->level = rhs.level;
	this->text = rhs.text;
	this->type = rhs.type;
	this->availability = rhs.availability;
	this->associatedClass = rhs.associatedClass;
	this->keywords = rhs.keywords;
	this->actionCost = rhs.actionCost;
	this->range = rhs.range;
	this->trigger = rhs.trigger;
	this->prerequisite = rhs.prerequisite;
	this->requirement = rhs.requirement;
	this->target = rhs.target;
	this->hit = rhs.hit;
	this->miss = rhs.miss;
	this->detail = rhs.detail;
	return *this;
}

QTextStream & operator>>(QTextStream &s, Power::PowerSource &data)
{
    int result;
    s >> result;
    data = Power::PowerSource(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, Power::RangeType &data)
{
    int result;
    s >> result;
    data = Power::RangeType(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, Power::ActionCost &data)
{
    int result;
    s >> result;
    data = Power::ActionCost(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, Power::PowerAvailability &data)
{
    int result;
    s >> result;
    data = Power::PowerAvailability(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, Power::PowerType &data)
{
    int result;
    s >> result;
    data = Power::PowerType(result);
    return s;
}
